package com.zd.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

import java.util.concurrent.*;

/**
 * 配置定时任务的线程池
 */
@Configuration
@EnableAsync
@Slf4j
public class ExecutorConfig {
    private static final int CORE_POOL_SIZE = 30;
    private static final int MAX_POOL_SIZE = 200;

    /**
     * 设置缓冲队列大小
     */
    private static final int QUEUE_CAPACITY = Integer.MAX_VALUE;
    private static final int KEEP_ALIVE_SECONDS = 10;
    private static final String NAME_PREFIX = "TaskThreadPool-普通任务--执行专用线程池";
    private static final String NAME_DATA_PREFIX = "TaskThreadPool-数据处理--执行专用线程池";

    private static final String NAME_SCHEDULER_PREFIX = "TaskThreadPool-定时任务--处理执行专用线程池";

    @Bean(name = "dataThreadPool")
    public ThreadPoolTaskExecutor threadPoolDataExecutor() {
        log.info("开启dataThreadPool的线程池！");
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor() {
            @Override
            protected BlockingQueue<Runnable> createQueue(int queueCapacity) {
                return new LinkedBlockingQueue<>(queueCapacity);
            }
        };
        executor.setCorePoolSize(CORE_POOL_SIZE);
        executor.setMaxPoolSize(MAX_POOL_SIZE);
        executor.setQueueCapacity(QUEUE_CAPACITY);
        executor.setKeepAliveSeconds(KEEP_ALIVE_SECONDS);
        executor.setThreadNamePrefix(NAME_DATA_PREFIX);
        // 当线程池没有处理能力的时候，该策略会直接在execute方法的调用线程中运行被拒绝的任务；如果执行程序已被关闭，则会丢弃该任务
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }

    @Bean(name = "taskThreadPool")
    public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
        log.info("开启taskThreadPool的线程池！");
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor() {
            @Override
            protected BlockingQueue<Runnable> createQueue(int queueCapacity) {
                return new LinkedBlockingQueue<>(queueCapacity);
            }
        };
        executor.setCorePoolSize(CORE_POOL_SIZE);
        executor.setMaxPoolSize(MAX_POOL_SIZE);
        executor.setQueueCapacity(QUEUE_CAPACITY);
        executor.setKeepAliveSeconds(KEEP_ALIVE_SECONDS);
        executor.setThreadNamePrefix(NAME_PREFIX);
        // 当线程池没有处理能力的时候，该策略会直接在execute方法的调用线程中运行被拒绝的任务；如果执行程序已被关闭，则会丢弃该任务
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }

    @Bean(name = "taskScheduler")   //ScheduledAnnotationBeanPostProcessor  自行了解原因
    public ThreadPoolTaskScheduler taskScheduler() {
        return new ThreadPoolTaskScheduler() {
            {
                setPoolSize(CORE_POOL_SIZE);
                setThreadNamePrefix(NAME_SCHEDULER_PREFIX);
                setAwaitTerminationSeconds(60);
                setWaitForTasksToCompleteOnShutdown(true);
                setErrorHandler(ex -> {
                    log.error("taskExecutor线程池异常", ex);
                });
            }
        };
    }
}
